package algo3.algothief.controlador;

import java.io.IOException;
import java.util.HashMap;
import java.io.BufferedReader;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import algo3.algothief.excepcion.CasoAunEnCursoException;
import algo3.algothief.excepcion.CasoNoIniciadoException;
import algo3.algothief.modelo.Juego;
import algo3.algothief.vista.VistaJuego;


public class ControladorInicioDelJuego {

	private Juego juego;
	
	private VistaJuego vistaDelJuego;
	
	private HashMap<String, Boolean> opcionesDeVerificacion;
	
//---------------------------------------------------------------------------------------------------------

	public ControladorInicioDelJuego(Juego juegoActual, VistaJuego vista) {
		this.juego = juegoActual;
		
		this.vistaDelJuego = vista;
		
		this.opcionesDeVerificacion = this.crearOpcionesDeVerificarSiElJugadorExiste();
	}
	
//---------------------------------------------------------------------------------------------------------
	
	private HashMap<String, Boolean> crearOpcionesDeVerificarSiElJugadorExiste() {
		HashMap<String, Boolean> opciones = new HashMap<String, Boolean>();
		
		opciones.put("S", true);
		opciones.put("N", false);
		opciones.put("s", true);
		opciones.put("n", false);
		
		return opciones;
	}
	
	private String procesarNombreDelJugador(BufferedReader entradaDeTeclado) throws IOException {
		String entrada = entradaDeTeclado.readLine();
		
		while (entrada.matches("")) {
			VistaJuego.graficarMensajeDeOpcionElegidaIncorrecta(entradaDeTeclado);
			
			vistaDelJuego.graficarMensajeParaIdentificarAlJugador();
			entrada = entradaDeTeclado.readLine();
		}
			
		return entrada;
	}
	
	private String procesarNombreDelJugadorOtraVez(BufferedReader entradaDeTeclado) throws IOException {
		String entrada = entradaDeTeclado.readLine();
		
		while (entrada.matches("")) {
			VistaJuego.graficarMensajeDeOpcionElegidaIncorrecta(entradaDeTeclado);
			
			vistaDelJuego.graficarMensajeParaReintentarLaIdentificacionDelJugador();
			entrada = entradaDeTeclado.readLine();
		}
			
		return entrada;
	}
	
	private boolean procesarOpcionParaCargarPartida(BufferedReader entradaDeTeclado) throws IOException {
		String entrada = entradaDeTeclado.readLine();
		
		while (!opcionesDeVerificacion.containsKey(entrada)) {
			VistaJuego.graficarMensajeDeOpcionElegidaIncorrecta(entradaDeTeclado);
			
			vistaDelJuego.graficarMenuParaVerificarSiNoEstaIdentificadoElJugador();
			entrada = entradaDeTeclado.readLine();
		}
			
		return opcionesDeVerificacion.get(entrada);
	}

	private boolean intentarCargarUnaPartidaGuardada(String nombreDelJugador, BufferedReader entradaDeTeclado) throws ParserConfigurationException, SAXException, IOException {
		boolean seCargoLaPartida = juego.cargarUnaPartida(nombreDelJugador);
		boolean elJugadorEsNuevo = false;
		
		while ((!seCargoLaPartida) && (!elJugadorEsNuevo)) {
			vistaDelJuego.graficarMenuParaVerificarSiNoEstaIdentificadoElJugador();
			elJugadorEsNuevo = this.procesarOpcionParaCargarPartida(entradaDeTeclado);
			
			if (!elJugadorEsNuevo) {
				vistaDelJuego.graficarMensajeParaReintentarLaIdentificacionDelJugador();
				nombreDelJugador = this.procesarNombreDelJugadorOtraVez(entradaDeTeclado);
				seCargoLaPartida = juego.cargarUnaPartida(nombreDelJugador);
			}
		}
		
		return seCargoLaPartida;
	}
	
	private void procesarEntradasDelJugadorConPartida(BufferedReader entradaDeTeclado) throws ParserConfigurationException, SAXException, IOException {
		String nombreDelJugador = juego.verElNombreDelJugador();
		
		vistaDelJuego.graficarMensajeParaIdentificacionExitosa(nombreDelJugador);
		
		vistaDelJuego.graficarMensajeDeGraduacionDelJugador(entradaDeTeclado);
	}
	
	private void procesarEntradasDelJugadorSinPartida(String nombreDelJugador, BufferedReader entradaDeTeclado) throws ParserConfigurationException, SAXException, IOException, CasoNoIniciadoException {
		vistaDelJuego.graficarMensajeParaIdentificacionExitosa(nombreDelJugador);
		
		vistaDelJuego.graficarMensajeDeGraduacionDelJugador(entradaDeTeclado);
	
		juego.definirNombreDelJugador(nombreDelJugador);
		this.iniciarNuevoCaso(entradaDeTeclado);
	}
	
//---------------------------------------------------------------------------------------------------------
	
	public void procesarEntradasInicialesDelJugador(BufferedReader entradaDeTeclado) throws ParserConfigurationException, SAXException, IOException, CasoNoIniciadoException {
		vistaDelJuego.graficarMensajeDeInicioDelJuego();
		entradaDeTeclado.readLine();
		
		vistaDelJuego.graficarMensajeParaIdentificarAlJugador();
		String nombreDelJugador = this.procesarNombreDelJugador(entradaDeTeclado);
		
		boolean seCargoLaPartida = this.intentarCargarUnaPartidaGuardada(nombreDelJugador, entradaDeTeclado);
			
		if (seCargoLaPartida)
			this.procesarEntradasDelJugadorConPartida(entradaDeTeclado);
		else 
			this.procesarEntradasDelJugadorSinPartida(nombreDelJugador, entradaDeTeclado);
	}
	
	public void iniciarNuevoCaso(BufferedReader entradaDeTeclado) throws ParserConfigurationException, SAXException, IOException, CasoNoIniciadoException {
		try {
			juego.iniciarNuevoCaso();
			vistaDelJuego.graficarMensajeDeIntroduccionAlCaso(entradaDeTeclado);
		} 
		catch (CasoAunEnCursoException excepcion) {
			// Nunca se llega a una situacion en la que no se haya terminado
			// el caso anterior antes de comenzar uno nuevo.
			VistaJuego.graficarMensajeDeError(excepcion);
		}
	}
}
